#!/usr/bin/python3.8
# -*- coding: utf-8 -*-
# @Time    : 2021/3/5 11:30
# @Author  : zhaohexin
# @Email   : 1483643520@xxx.com
# @File    : curd.py
# @Software: PyCharm
# @FileDescription：通用接口校验函数

from sqlalchemy.orm import Session

from datetime import datetime, timedelta
from typing import Optional
from fastapi import Depends, HTTPException, status
from jose import JWTError, jwt
from common.Oauth2PasswordBearer import OAuth2Password

from common.Security import verify_password
from core.config import settings
from apps.system.users.crud import get_user, get_user_by_username
from common.Exception import NormalException
from common.Redis import RedisCli


oauth2_scheme = OAuth2Password(tokenUrl="login_swagger")


def authenticate_user(db: Session, username: str, password: str):
    """
    校验用户名是否正确
    :param db:
    :param username: 用户名
    :param password: 密码
    :return: 无用户名返回无用户名，密码错误返回密码错误， 正确返回用户信息
    """
    user = get_user_by_username(db, username)
    if not user:
        raise NormalException(
            status=status.HTTP_400_BAD_REQUEST,
            message="用户名密码错误！"
        )
    if not verify_password(password, user.password):
        raise NormalException(
            status=status.HTTP_400_BAD_REQUEST,
            message="用户名或密码错误！"
        )
    return user


def authenticate_img_code(uuid: str, code: str):
    """
    校验验证码是否正确
    :param uuid: uuid
    :param code: 前端结果
    :return:
    """
    # 查询验证码是否正确
    redis = RedisCli("image_code")
    result = redis.__getitem__(uuid)
    if not result:
        raise NormalException(
            status=status.HTTP_400_BAD_REQUEST,
            message="验证码过期或者不存在！"

        )
    if result != code:
        raise NormalException(status=status.HTTP_400_BAD_REQUEST,
                              message="验证码错误请重新输入！")


def create_access_token(data: dict, expires: Optional[timedelta] = None):
    """
    创建token
    :param data:
    :param expires:
    :return:
    """
    to_encode = data.copy()
    if expires:
        expire = datetime.utcnow() + expires
    else:
        expire = datetime.utcnow() + timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
    to_encode.update({"exp": expire})
    encode_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM)
    return encode_jwt


async def get_current_user(db: Session, token: str = Depends(oauth2_scheme)):
    """
    获取用户信息
    :param db:
    :param token:
    :return:
    """
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="用户信息校验失败"
    )
    try:
        paload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
        username: str = paload.get("sub")
        if username is None:
            raise credentials_exception
    except JWTError:
        raise credentials_exception
    user = get_user(db, username=username)
    if user is None:
        raise credentials_exception
    return user


async def check_token(token: str = Depends(oauth2_scheme)):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="用户信息校验失败"
    )
    try:
        paload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
        username: str = paload.get("sub")
        if username is None:
            raise credentials_exception
    except JWTError:
        raise credentials_exception
    return username
